package remoteCommand

import (
	"bytes"
	"encoding/binary"
)

//请求码  namesrv 0~99   broker 100 ~ 255
const (
	//向namesrv注册broker
	REGISTER_BROKER int16 = 0
	//向namesrv注销broker
	UNREGISTER_BROKER int16 = 1
)

//响应码
const (
	SUCCESS int16 = 0
)

//响应类型
const (
	REQUEST_COMMAND  = 0 //请求
	RESPONSE_COMMAND = 1 //响应
)

type CmdHeader struct {
	Code int16 //指令

	Version int8 //指令版本号

	Opaque int64 //请求和响应标识id

	ClientId string //客户端id

	Flag int8 // 0.请求  1.响应
}

type RemoteCommand struct {
	Header *CmdHeader
	Body   []byte
}

func Decode(array []byte) *RemoteCommand {
	cmd := &RemoteCommand{
		&CmdHeader{},
		nil,
	}
	buf := bytes.NewBuffer(array)
	_ = binary.Read(buf, binary.LittleEndian, &cmd.Header.Code)
	_ = binary.Read(buf, binary.LittleEndian, &cmd.Header.Version)
	_ = binary.Read(buf, binary.LittleEndian, &cmd.Header.Opaque)
	var clientIdLength int8
	_ = binary.Read(buf, binary.LittleEndian, &clientIdLength)
	clientIdBytes := make([]byte, clientIdLength)
	if _, err := buf.Read(clientIdBytes); err != nil {
		panic(err)
	}
	cmd.Header.ClientId = string(clientIdBytes)
	_ = binary.Read(buf, binary.LittleEndian, &cmd.Header.Flag)

	cmd.Body = buf.Bytes()
	return cmd
}

func (c *RemoteCommand) Encode() []byte {
	buf := bytes.NewBuffer([]byte{})
	h := c.Header
	//写入header
	if err := binary.Write(buf, binary.LittleEndian, h.Code); err != nil {
		panic(err)
	}
	if err := binary.Write(buf, binary.LittleEndian, h.Version); err != nil {
		panic(err)
	}
	if err := binary.Write(buf, binary.LittleEndian, h.Opaque); err != nil {
		panic(err)
	}
	clientIdBytes := []byte(h.ClientId)
	if err := binary.Write(buf, binary.LittleEndian, int8(len(clientIdBytes))); err != nil {
		panic(err)
	}
	if err := binary.Write(buf, binary.LittleEndian, clientIdBytes); err != nil {
		panic(err)
	}
	if err := binary.Write(buf, binary.LittleEndian, h.Flag); err != nil {
		panic(err)
	}
	//写入body
	if err := binary.Write(buf, binary.LittleEndian, c.Body); err != nil {
		panic(err)
	}

	return buf.Bytes()

}

//标记为响应类型
func (c *RemoteCommand) MarkResponseType() {
	c.Header.Flag = 1
}

//获取命令类型
func (c *RemoteCommand) GetType() int {
	if c.Header.Flag == REQUEST_COMMAND {
		return REQUEST_COMMAND
	}
	return RESPONSE_COMMAND
}
